<template>
  <div class="common-form">
    <el-form :model="props.model" :inline="inline" :label-width="labelWidth">
      <el-form-item v-for="formItem in formJson" :key="formItem.field" :label="formItem.label">
        <slot v-if="slots[formItem.field]" :name="formItem.field" />
        <el-input
            v-else-if="formItem.type==='text' || formItem.type==='password' || formItem.type==='textarea'"
            :type="formItem.type"
            v-model.trim="props.model[formItem.field]"
            clearable
            :class="formItem.className"
            :minlength="formItem.minlength || 0"
            :maxlength="formItem.maxlength || 142"
            :show-word-limit="formItem.showWordLimit"
            :rows="formItem.rows || 2"
            :show-password="formItem.showPassword??true"
            :disabled="formItem.disabled"
            :readonly="formItem.readonly"
            :placeholder="getPlaceholder(formItem.type,formItem.placeholder)"
            @change="handleFormItemChange(formItem)"
        />
        <el-input-number
            v-else-if="formItem.type==='number'"
            v-model.trim="props.model[formItem.field]"
            clearable
            :class="formItem.className"
            :min="formItem.min || -Infinity"
            :max="formItem.max || Infinity"
            :step="formItem.step || 1"
            :disabled="formItem.disabled"
            :readonly="formItem.readonly"
            :placeholder="getPlaceholder(formItem.type,formItem.placeholder)"
            @change="handleFormItemChange(formItem)"
        />
        <el-select
            v-else-if="formItem.type==='select'"
            :class="formItem.className"
            :popper-class="formItem.popperClass"
            v-model="props.model[formItem.field]"
            clearable
            filterable
            :teleported="formItem.teleported??true"
            :disabled="formItem.disabled"
            :multiple="formItem.multiple"
            :multiple-limit="formItem.multipleLimit || 0"
            :collapse-tags="formItem.collapseTags??true"
            :collapse-tags-tooltip="formItem.collapseTagsTooltip??true"
            :placeholder="getPlaceholder(formItem.type,formItem.placeholder)"
            @focus="handleFormItemFocus(formItem)"
        >
          <el-option
              v-for="selectItem in formItem.options??[]"
              :key="selectItem[formItem.props?.value||'value']"
              :label="selectItem[formItem.props?.label||'label']"
              :value="selectItem[formItem.props?.value||'value']"
          />
        </el-select>
        <el-cascader
            v-else-if="formItem.type==='cascader'"
            :class="formItem.className"
            :popper-class="formItem.popperClass"
            v-model="props.model[formItem.field]"
            :options="formItem.options??[]"
            :props="formItem.props??{}"
            clearable
            filterable
            :disabled="formItem.disabled"
            :show-all-levels="formItem.showAllLevels??true"
            :teleported="formItem.teleported??true"
            :collapse-tags="formItem.collapseTags??true"
            :collapse-tags-tooltip="formItem.collapseTagsTooltip??true"
            :separator="formItem.separator??'/'"
            :placeholder="getPlaceholder(formItem.type,formItem.placeholder)"
            @focus="handleFormItemFocus(formItem)"
        >
        </el-cascader>
        <el-tree-select
            v-else-if="formItem.type==='treeSelect'"
            :class="formItem.className"
            :popper-class="formItem.popperClass"
            v-model="props.model[formItem.field]"
            :data="formItem.options??[]"
            :props="formItem.props??{}"
            :check-strictly="formItem.props?.checkStrictly??false"
            clearable
            filterable
            :teleported="formItem.teleported??true"
            :disabled="formItem.disabled"
            :multiple="formItem.multiple"
            :multiple-limit="formItem.multipleLimit || 0"
            :collapse-tags="formItem.collapseTags??true"
            :collapse-tags-tooltip="formItem.collapseTagsTooltip??true"
            :placeholder="getPlaceholder(formItem.type,formItem.placeholder)"
            @focus="handleFormItemFocus(formItem)"
        />
        <el-date-picker
            v-else-if="singleDateTypeList.includes(formItem.type)"
            v-model="props.model[formItem.field]"
            :class="formItem.className"
            :popper-class="formItem.popperClass"
            :type="formItem.type"
            clearable
            :format="formItem.format || 'YYYY-MM-DD'+(formItem.type==='datetime'?' HH:mm:ss':'')"
            :value-format="formItem.valueFormat || 'YYYY-MM-DD'+(formItem.type==='datetime'?' HH:mm:ss':'')"
            :disabled="formItem.disabled"
            :readonly="formItem.readonly"
            :disabled-date="(time)=>getDisabledDate(time,formItem)"
            :teleported="formItem.teleported??true"
            :placeholder="getPlaceholder(formItem.type,formItem.placeholder)"
        />
        <el-date-picker
            v-else-if="rangeDateTypeList.includes(formItem.type)"
            v-model="props.model[formItem.field]"
            :class="formItem.className"
            :popper-class="formItem.popperClass"
            :type="formItem.type"
            clearable
            :format="formItem.format || 'YYYY-MM-DD'+(formItem.type==='datetimerange'?' HH:mm:ss':'')"
            :value-format="formItem.valueFormat || 'YYYY-MM-DD'+(formItem.type==='datetimerange'?' HH:mm:ss':'')"
            :disabled="formItem.disabled"
            :readonly="formItem.readonly"
            :disabled-date="(time)=>getDisabledDate(time,formItem)"
            :teleported="formItem.teleported??true"
            :default-time="defaultTime"
            :unlink-panels="formItem.unlinkPanels??true"
            :start-placeholder="getPlaceholder(formItem.type,formItem.startPlaceholder??'开始时间')"
            :end-placeholder="getPlaceholder(formItem.type,formItem.endPlaceholder??'结束时间')"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleSearch">查询</el-button>
        <el-button>重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script setup lang="ts" name="CommonForm">
// import {cloneDeep} from "lodash";
import axios from "axios";
import { useSlots,computed } from "vue";
const slots = useSlots()

// props类型
type Props = {
  model: Record<string, any>
  formJson: FormItem[],
  inline?: boolean,
  labelWidth?: string|number
}
const emit = defineEmits(['change'])
const props = withDefaults(defineProps<Props>(), {
  model: ()=>({}),
  formJson: ()=>[],
  inline: false,
  labelWidth: '80px'
})

// 后台请求ip
const requestIp = computed(()=>{
  return 'http://localhost:8081'
})

const singleDateTypeList = ['date','datetime','week','month','year','dates']
const rangeDateTypeList = ['daterange','datetimerange','monthrange','yearrange']

const defaultTime: [Date, Date] = [
  new Date(2000, 1, 1, 0, 0, 0),
  new Date(2000, 2, 1, 23, 59, 59),
]

// 获取"占位符"
const getPlaceholder = (placeholderType:string,placeholderText:string|undefined)=>{
  const inputTypeList = ['text','textarea','number','password']
  if(inputTypeList.includes(placeholderType)) {
    return placeholderText?placeholderText:'请输入'
  }
  return placeholderText?placeholderText:'请选择'
}
// 获取"禁用日期"
const getDisabledDate = (time:Date,formItem:FormItem)=>{
  if(formItem.disabledDateType){
    const disabledDateTypeMap = {
      before:time.getTime() < Date.now() - 8.64e7,
      after:time.getTime() > Date.now()
    }
    return disabledDateTypeMap[formItem.disabledDateType]
  }
  return false
}

const handleFormItemChange = (formItem:FormItem)=>{
  emit('change',formItem)
}
const handleFormItemFocus = async (formItem:FormItem)=>{
  // 如果options有值，说明已经获取过了，不需要再次获取
  if(formItem.optionState&&formItem.options&&formItem.options.length>0){
    return false
  }
  switch (formItem.optionsFrom) {
    // 模拟通过字典dict获取
    case 'dict':
      formItem.options = [{
        label:'选项1',
        value:'1'
      },{
        label:'选项2',
        value:'2'
      }]
      break
    // 通过前端提供api方法获取
    case 'frontendApi':
      try {
        if(formItem.optionsApi){
          const { code,data } = await formItem.optionsApi()
          formItem.options = data
        }
      }catch (e) {}
      break
      // 通过后端提供api url与方式 获取
    case 'backendApi':
      axios[formItem.optionsApiType??'get'](requestIp.value + formItem.optionsApi).then(res=>{
        const { code,data } = res.data
        if(code === 200 || code === 0){
          formItem.options = data
        }
      }).catch(err=>{
        console.log(err)
      })

      break
    default:
      break
  }
  // 已经获取过options
  formItem.optionState = true
}
const handleSearch = ()=>{
  console.log(props.model)
}
</script>
